package com.powergisol.gis.service.impl;


import com.alibaba.druid.support.json.JSONUtils;
import com.powergisol.gis.dao.TabDataSettingMapper;
import com.powergisol.gis.dao.TabLayerMapper;
import com.powergisol.gis.dao.TabSceneMapper;
import com.powergisol.gis.dao.TabTreeMapper;
import com.powergisol.gis.entity.*;
import com.powergisol.gis.exception.GlobalExceptionHandler;
import com.powergisol.gis.service.TabSceneService;
import com.powergisol.gis.util.FileUtil;
import com.powergisol.gis.util.Result;
import com.powergisol.gis.vo.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Log4j2
public class TabSceneServiceImpl implements TabSceneService {
    @Autowired
    private TabSceneMapper tabSceneMapper;
    @Autowired
    private TabLayerMapper tabLayerMapper;
    @Autowired
    private TabTreeMapper tabTreeMapper;
    @Autowired
    private TabDataSettingMapper settingMapper;

    @Value("${scene-url}")
    private String sceneUrl;

    @Override
    public List<Map<String, Object>> listScene(TabScene tabScene) {
        return tabSceneMapper.listScene(tabScene);
    }

    @Override
    @Transactional
    public Result saveScene(TabScene tabScene, Integer userId) {
        Result result = new Result();
        if (null == tabScene.getSceneName()) {
            return result.failure(405, "场景名称不能为空");
        }
        //场景名称验证
        TabScene tabScene1 = tabSceneMapper.getSceneByName(tabScene.getSceneName(), null);
        if (null != tabScene1) {
            return result.failure(405, "场景名称重复");
        }

        tabScene.setSceneUrl(sceneUrl + tabScene.getSceneName());
        Date date = new Date();
        tabScene.setCreateTime(date);
        tabScene.setUpdateTime(date);
        tabSceneMapper.saveScene(tabScene);
        tabSceneMapper.saveSceneUser(userId, tabScene.getId());
        //默认新建一个树节点
        TabTree tabTree = new TabTree();
        tabTree.setSceneId(tabScene.getId());
        tabTree.setTreeName(tabScene.getSceneName());
        tabTreeMapper.saveTree(tabTree);
        //生成默认文件
        defaultFile(tabTree);
        TabSceneVo vo = new TabSceneVo();
        vo.setTabScene(tabScene);
        vo.setTreeId(tabTree.getId());
        result.setData(vo);
        return result;
    }

    @Override
    public Result upScene(TabScene tabScene, Integer userId) {
        Result result = new Result();
        if (null == tabScene.getSceneName()) {
            return result.failure(405, "场景名称不能为空");
        }
        //场景名称验证
        TabScene tabScene1 = tabSceneMapper.getSceneByName(tabScene.getSceneName(), null);
        if (null != tabScene1 && !tabScene.getId().equals(tabScene1.getId())) {
            return result.failure(405, "场景名称重复");
        }
        tabScene.setUpdateTime(new Date());
        tabScene.setSceneUrl(sceneUrl + tabScene.getSceneName());
        tabSceneMapper.upScene(tabScene);
        result.setData(tabScene);
        return result;
    }

    @Override
    public Result treeScene(Integer sceneId, Integer userId) {
        Result result = new Result();
        List<Map<String, Object>> sceneList = tabSceneMapper.listSceneTree(sceneId, userId);
        getNextTree(sceneList);
        result.setData(sceneList);
        return result;
    }

    @Override
    public Result sceneDetail(Integer sceneId) {
        Result result = new Result();
        TabScene tabScene = tabSceneMapper.getById(sceneId);
        result.setData(tabScene);
        return result;
    }

    @Override
    public Result delScene(Integer id, Integer upSceneId, Integer userId) {
        Result result = new Result();
        TabTree tree = new TabTree();
        tree.setId(id);
        TabTree tabTree = tabTreeMapper.getByCondition(tree);
        if (null == tabTree) {
            return result.failure(404, "数据不存在");
        }
        if (null != tabTree.getSceneId()) {
            TabScene tabScene = tabSceneMapper.getById(tabTree.getSceneId());
            //删除场景
            tabSceneMapper.delScene(tabScene.getId());
            //删除用户场景中间表
            tabSceneMapper.delUserScene(tabScene.getId());
        } else {
            TabScene tabScene = tabSceneMapper.getById(upSceneId);
            tabScene.setUpdateTime(new Date());
            tabSceneMapper.upScene(tabScene);
        }
        //删除文件及相关数据，包括子文件夹、图层数据
        delNext(tabTree);

        return result;
    }

    private void delNext(TabTree tree) {
        if (null == tree) {
            return;
        }
        if (1 == tree.getIsLayer()) {
            //删除树节点及图层数据
            tabTreeMapper.delTree(tree.getId());
            tabLayerMapper.deleteLayerById(tree.getLayerId());
            tabLayerMapper.deleteSceneLayerById(tree.getLayerId());
        } else {
            Integer pId = tree.getId();
            List<TabTree> trees = tabTreeMapper.listTabTree(pId);
            tabTreeMapper.delTree(tree.getId());
            for (TabTree tr : trees) {
                delNext(tr);
            }
        }
    }


    @Override
    public Result saveTree(TabTree tabTree) {
        Result result = new Result();
        if (null == tabTree.getTreeName()) {
            return result.failure(405, "树菜单名称不能为空");
        }
        //如果有layerId
        if (null != tabTree.getLayerId()) {
            tabTree.setIsLayer(1);
        }
        //获取pId下最大排序值
        Integer maxSort = tabTreeMapper.getMaxSort(tabTree.getpId());
        tabTree.setTreeSort(null == maxSort ? 0 : maxSort + 1);
        tabTreeMapper.saveTree(tabTree);
        //场景修改
        TabScene tabScene = tabSceneMapper.getById(tabTree.getUpSceneId());
        tabScene.setUpdateTime(new Date());
        tabSceneMapper.upScene(tabScene);

        result.setData(tabTree);
        return result.success("保存成功");
    }

    @Override
    public Result upTree(TabTree tabTree) {
        Result result = new Result();

        if (null == tabTree.getTreeName()) {
            return result.failure(405, "树菜单名称不能为空");
        }
        TabScene tabScene = tabSceneMapper.getById(tabTree.getUpSceneId());
        tabScene.setUpdateTime(new Date());
        if (null == tabTree.getpId() || ("").equals(tabTree.getpId())) {
            tabScene.setSceneName(tabTree.getTreeName());
        }
        tabSceneMapper.upScene(tabScene);
        //根据ID查询出当前树的ISlayer属性
        TabTree tree = tabTreeMapper.getById(tabTree.getId());
        tabTree.setIsLayer(tree.getIsLayer());
        //如果树为图层信息，则需要修改图层
        if (null != tabTree.getIsLayer() && 1 == tabTree.getIsLayer()) {
            TabLayer tabLayer = tabLayerMapper.getLayerById(tabTree.getLayerId());
            if (null != tabLayer && null != tabTree.getTreeName()) {
                tabLayer.setLayerName(tabTree.getTreeName());
                tabLayerMapper.upLayer(tabLayer);
            }
        }
        tabTreeMapper.upTree(tabTree);
        result.setData(tabTree);
        return result.success("修改成功");
    }

    @Override
    public Result saveLayer(TabLayer tabLayer) {
        Result result = new Result();

        TabServiceVo vo = settingMapper.getByServiceName(tabLayer.getServiceName());
        if (null == vo) {
            return result.failure(500, "该服务不存在");
        }
        //判断当前场景下是否存在该服务
        Integer serviceNum = tabLayerMapper.countServiceNum(tabLayer.getSceneId(), vo.getId());
        if (serviceNum > 0) {
            return result.failure(415, "该场景下服务已存在");
        }
        tabLayer.setServiceId(vo.getId());
        tabLayer.setServiceUrl(vo.getServiceUrl());
        tabLayer.setLayerType(vo.getServiceType());
        tabLayerMapper.saveLayer(tabLayer);

        //TODO 是否查询当前treeId对应的场景id
        TabSceneLayer tabSceneLayer = new TabSceneLayer();
        tabSceneLayer.setTabSceneId(tabLayer.getSceneId());
        tabSceneLayer.setTabLayerId(tabLayer.getId());
        tabLayerMapper.saveSceneLayer(tabSceneLayer);
        //保存至树下
        TabTree tabTree = null;
        if (tabLayer.getFileId() == null) {
            List<DynamicPara> dynamicParaList = tabLayerMapper.getDynamic();
            Map<Integer, List<DynamicPara>> collect = dynamicParaList.stream().collect(Collectors.groupingBy(DynamicPara::getFolderType));
            boolean tag = true;
            for (Integer x : collect.keySet()) {
                List<Integer> fileType = collect.get(x).stream().map(d -> d.getFileType()).collect(Collectors.toList());
                if (fileType.contains(vo.getServiceType())) {
                    tabTree = saveData(tabLayer, x);
                    tag = false;
                }
            }
            if (tag) {
                tabTree = new TabTree();
                tabTree.setIsLayer(1);
                tabTree.setpId(tabLayer.getTreeId());
                tabTree.setTreeName(tabLayer.getLayerName());
                tabTree.setLayerId(tabLayer.getId());
                //获取pid下最大排序值
                Integer maxSort = tabTreeMapper.getMaxSort(tabLayer.getTreeId());
                tabTree.setTreeSort(null == maxSort ? 0 : maxSort + 1);
                tabTreeMapper.saveTree(tabTree);
            }
        } else {
            tabTree = new TabTree();
            tabTree.setIsLayer(1);
            tabTree.setpId(tabLayer.getFileId());
            tabTree.setTreeName(tabLayer.getLayerName());
            tabTree.setLayerId(tabLayer.getId());
            //获取pid下最大排序值
            Integer maxSort = tabTreeMapper.getMaxSort(tabLayer.getFileId());
            tabTree.setTreeSort(null == maxSort ? 0 : maxSort + 1);
            tabTreeMapper.saveTree(tabTree);
        }

        //场景修改
        TabScene tabScene = tabSceneMapper.getById(tabLayer.getSceneId());
        tabScene.setUpdateTime(new Date());
        tabSceneMapper.upScene(tabScene);

        result.setData(tabTree);
        return result;
    }

    private TabTree saveData(TabLayer tabLayer, Integer type) {
        TabTree tabTree;
        Integer id = tabTreeMapper.getBySceneId(tabLayer.getSceneId());
        Integer fileId = tabTreeMapper.selTree(id, type);
        tabTree = new TabTree();
        tabTree.setIsLayer(1);
        tabTree.setpId(null == fileId ? tabLayer.getTreeId() : fileId);
        tabTree.setTreeName(tabLayer.getLayerName());
        tabTree.setLayerId(tabLayer.getId());
        tabTree.setUpdateTime(new Date());
        Integer maxSort;
        if (fileId == null) {
            maxSort = tabTreeMapper.getMaxSort(tabLayer.getTreeId());
        } else {
            //获取pid下最大排序值
            maxSort = tabTreeMapper.getMaxSort(fileId);
        }
        tabTree.setTreeSort(null == maxSort ? 0 : maxSort + 1);
        tabTreeMapper.saveTree(tabTree);
        return tabTree;
    }

    @Override
    public Result getSceneById(Integer id) {
        TabScene tabScene = tabSceneMapper.getById(id);
        Result result = new Result();
        result.setData(tabScene);
        return result;
    }

    /**
     * 删除场景
     *
     * @param sceneId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public Result deleteScene(Integer sceneId) {
        log.info("用户删除场景ID为:{}", sceneId);
        try {
            //删除场景和用户的关系
            tabSceneMapper.delUserScene(sceneId);
            //删除场景
            tabSceneMapper.delScene(sceneId);
            //根据场景ID得到tree的ID
            Integer treeId = tabTreeMapper.getBySceneId(sceneId);
            //找到tree中父级ID是tree的id的
            List<TabTree> trees = tabTreeMapper.getSceneById(treeId);

            List<Integer> treeIds = null;
            List<Integer> layerIds = null;
            if (!trees.isEmpty() && trees.size() > 0) {
                //筛选出那些父级ID是treeID的
                treeIds = trees.stream().map(s -> s.getId()).collect(Collectors.toList());
                //筛选出layerID
                layerIds = trees.stream().map(s -> s.getLayerId()).collect(Collectors.toList());
            }
            if (treeIds != null && !treeIds.isEmpty() && treeIds.size() > 0) {
                tabTreeMapper.deleteTreeById(treeIds);
            }
            if (layerIds != null && layerIds.isEmpty() && layerIds.size() > 0) {
                tabLayerMapper.delByIds(layerIds);
            }
            tabTreeMapper.delTree(treeId);
            tabLayerMapper.deleteSceneLayerById(sceneId);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GlobalExceptionHandler(400, "场景删除失败");
        }
        return new Result().success("删除成功");
    }

    @Override
    public Result copyScene(CopyTreeVo tabSceneVo) {
        StringBuffer sb = new StringBuffer();
        Result result = new Result();
        //修改场景
        TabScene tabScene = tabSceneMapper.getById(tabSceneVo.getSceneId());
        tabScene.setUpdateTime(new Date());
        tabSceneMapper.upScene(tabScene);
        //获取该场景对应的树id
        TabTree condition = new TabTree();
        condition.setSceneId(tabSceneVo.getSceneId());
        TabTree tabTree = tabTreeMapper.getByCondition(condition);
        //获取该场景下已存在的图层
        List<String> scenceLayer = getLayer(tabSceneVo.getSceneId());
        //是否按结构(1是0否)
        if (tabSceneVo.getIsStructure() == 1) {
            //获取场景树
            List<TabTree> listScene = getScene(tabSceneVo.getTreeList());
            //循环获取场景树下的对应的节点
            for (TabTree tree : listScene) {
                //获取该场景下已存在的图层
                getTreeByPid(tabSceneVo, tree.getId(), tabTree.getId(),sb,scenceLayer);
            }
        } else {
            List<TabTree> listScene = getLayer(tabSceneVo.getTreeList());
            for (TabTree layerTree : listScene) {
                TabTree saveTree = new TabTree();
                saveTree.setpId(tabTree.getId());
                saveTree.setTreeName(layerTree.getTreeName());
                //获取pid下最大排序值
                Integer maxSort = tabTreeMapper.getMaxSort(tabTree.getId());
                saveTree.setTreeSort(null == maxSort ? 1 : maxSort + 1);
                //保存图层
                TabLayer tab = new TabLayer();
                TabLayer tabLayered = tabLayerMapper.getLayerById(layerTree.getLayerId());
                TabServiceVo vo = settingMapper.getBySerId(tabLayered.getServiceId());
                boolean b = scenceLayer.stream().anyMatch(str -> str.equals(vo.getName()));
                if(b){
                    sb.append(tabLayered.getServiceName()+",");
                    continue;
                }

                tab.setLayerName(tabLayered.getLayerName());
                tab.setLayerType(tabLayered.getLayerType());
                tab.setServiceId(tabLayered.getServiceId());
                tab.setServiceUrl(tabLayered.getServiceUrl());
                tabLayerMapper.saveLayer(tab);

                TabSceneLayer tabSceneLayer = new TabSceneLayer();
                tabSceneLayer.setTabSceneId(tabSceneVo.getSceneId());
                tabSceneLayer.setTabLayerId(tab.getId());
                tabLayerMapper.saveSceneLayer(tabSceneLayer);
                //保存树
                saveTree.setIsLayer(1);
                saveTree.setLayerId(tab.getId());
                tabTreeMapper.saveTree(saveTree);
                scenceLayer.add(tabLayered.getServiceName());
            }
        }
        if(sb.length()>0){
            sb.delete(sb.length()-1,sb.length());
            sb.append("图层已在该场景下");
        }else{
            sb.append("导入图层成功");
        }
        result.setData(sb.toString());
        return result;
    }

    private List<Map<String, Object>> getNextTree(List<Map<String, Object>> treeList) {
        List<Map<String, Object>> subMenuList = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> map : treeList) {
            if ("0".equals(map.get("isLayer")) || 0 == Integer.valueOf(map.get("isLayer").toString())) {
                List<Map<String, Object>> list = tabSceneMapper.listTreeById(map.get("id").toString());
                map.put("children", getNextTree(list));
            } else {
                map.put("children", new ArrayList<>());
            }
            subMenuList.add(map);
        }
        return subMenuList;
    }

    /**
     * @param list
     * @return
     */
    private List<TabTree> getLayer(List<TabTree> list) {
        List<TabTree> listTree = new ArrayList<>();
        for (TabTree item : list) {
            if (null != item.getLayerId()) {
                listTree.add(item);
            }
        }
        return listTree;
    }

    /**
     * 获取该场景下所有图层
     * @param scenceId
     * @return
     */
    private List<String> getLayer(Integer scenceId) {
        return tabSceneMapper.getLayerByScenceId(scenceId);
    }


    /**
     * 获取场景树
     *
     * @param list
     * @return
     */
    private List<TabTree> getScene(List<TabTree> list) {
        List<TabTree> listTree = new ArrayList<>();
        for (TabTree item : list) {
            if (null != item.getSceneId()) {
                listTree.add(item);
            }
        }
        return listTree;
    }

    /**
     * 当前树节点，如果树的父id当前树节点，则证明是下一级
     *
     * @param tabSceneVo
     * @param id
     * @param pid
     */
    private void getTreeByPid(CopyTreeVo tabSceneVo, Integer id, Integer pid,StringBuffer sb, List<String> scenceLayer) {
        List<TabTree> listTree = new ArrayList<>();
        List<TabTree> listTreeItem = tabSceneVo.getTreeList();
        for (TabTree tree : listTreeItem) {
            if (null != tree.getpId() && tree.getpId().equals(id)) {
                listTree.add(tree);
            }
        }
        for (TabTree tree : listTree) {
            TabTree saveTree = new TabTree();
            saveTree.setSceneId(tree.getSceneId());
            saveTree.setpId(pid);
            saveTree.setTreeName(tree.getTreeName());
            //获取pid下最大排序值
            Integer maxSort = tabTreeMapper.getMaxSort(pid);
            saveTree.setTreeSort(null == maxSort ? 1 : maxSort + 1);
            saveTree.setUpdateTime(new Date());
            if (tree.getIsLayer() == 1) {
                //保存图层
                TabLayer tab = new TabLayer();
                TabLayer tabLayered = tabLayerMapper.getLayerById(tree.getLayerId());
                TabServiceVo vo = settingMapper.getBySerId(tabLayered.getServiceId());
                boolean b = scenceLayer.stream().anyMatch(str -> str.equals(vo.getName()));
                if(b){
                    sb.append(tabLayered.getServiceName()+",");
                    continue;
                }
                tab.setLayerName(tabLayered.getLayerName());
                tab.setLayerType(tabLayered.getLayerType());
                tab.setServiceId(tabLayered.getServiceId());
                tab.setServiceUrl(tabLayered.getServiceUrl());
                tabLayerMapper.saveLayer(tab);

                TabSceneLayer tabSceneLayer = new TabSceneLayer();
                tabSceneLayer.setTabSceneId(tabSceneVo.getSceneId());
                tabSceneLayer.setTabLayerId(tab.getId());
                tabLayerMapper.saveSceneLayer(tabSceneLayer);
                //保存树
                saveTree.setIsLayer(1);
                saveTree.setLayerId(tab.getId());
                tabTreeMapper.saveTree(saveTree);
                scenceLayer.add(tabLayered.getServiceName());
            } else {
                saveTree.setIsLayer(0);
                tabTreeMapper.saveTree(saveTree);
                getTreeByPid(tabSceneVo, tree.getId(), saveTree.getId(),sb, scenceLayer);
            }
        }
    }

    @Override
    public void updateSort(List<TreeSortVO> sortVOList) {
        if (sortVOList == null && sortVOList.isEmpty()) {
            throw new GlobalExceptionHandler(400, "没有排序信息");
        }
        sortVOList.forEach(s -> {
            tabTreeMapper.updateSort(s);
        });
    }

    @Override
    public void updateTreeSort(TreeSortDataVO treeSortDataVO) {
        //根据id获取树
        TabTree tree = new TabTree();
        tree.setId(treeSortDataVO.getId());
        tree = tabTreeMapper.getByCondition(tree);
        tree.setUpdateTime(new Date());
        tree.setpId(treeSortDataVO.getPId());

        Integer startSort = treeSortDataVO.getStartSort();
        Integer endSort = 1000;
        if (treeSortDataVO.getIsChange() != 1) {
            endSort = treeSortDataVO.getEndSort() - startSort;
            if (treeSortDataVO.getIsBack() == 1) {
                startSort = startSort + 1;
            }
        }

        List<TabTree> list = tabTreeMapper.listTabTreeLimit(treeSortDataVO.getPId(), startSort, endSort);
        if (treeSortDataVO.getIsBack() == 1) {
            list.sort((TabTree ord1, TabTree ord2) -> ord2.getTreeSort().compareTo(ord1.getTreeSort()));
        }

        for (int i = 0; i < list.size(); i++) {
            TabTree tabTree = new TabTree();
            tabTree = list.get(i);
            if (treeSortDataVO.getIsChange() == 1) {
                tabTree.setTreeSort(treeSortDataVO.getSort() + 1 + i);
            } else {
                if (treeSortDataVO.getIsBack() == 1) {
                    tabTree.setTreeSort(treeSortDataVO.getSort() - 1 - i);
                } else {
                    tabTree.setTreeSort(treeSortDataVO.getSort() + 1 + i);
                }
            }
            tabTreeMapper.upTree(tabTree);
        }
        tree.setTreeSort(treeSortDataVO.getSort());
        tabTreeMapper.upTree(tree);

//        List<TabTree> listPre = tabTreeMapper.listTabTreePre(treeSortDataVO.getPId(),treeSortDataVO.getSort());
//        for(int i=0;i<listPre.size(); i++){
//            TabTree tabTree =  listPre.get(i);
//            tabTree.setTreeSort(i);
//            tabTreeMapper.upTree(tabTree);
//        }
//
//        List<TabTree> listNext = tabTreeMapper.listTabTreeNext(treeSortDataVO.getPId(),treeSortDataVO.getSort());
//        for(int i=0;i<listNext.size(); i++){
//            TabTree tabTree =  listNext.get(i);
//            tabTree.setTreeSort(i+treeSortDataVO.getSort()+1);
//            tabTreeMapper.upTree(tabTree);
//        }

//        //修改同级为+1
//        if(null != treeSortDataVO.getIsBack() && treeSortDataVO.getIsBack()==1){
//            treeSortDataVO.setSort(treeSortDataVO.getSort()+1);
//            tabTreeMapper.upTreeSortBack(treeSortDataVO);
//        }else{
//            tabTreeMapper.upTreeSort(treeSortDataVO);
//        }


        //场景修改
        TabScene tabScene = tabSceneMapper.getById(treeSortDataVO.getUpSceneId());
        tabScene.setUpdateTime(new Date());
        tabSceneMapper.upScene(tabScene);
    }

    private void defaultFile(TabTree tabTree) {
        List<TabTree> treeList = new ArrayList<>();
        List<LinkedHashMap<String, String>> tempTreeList = new ArrayList<>();
        Resource resource = new ClassPathResource("json/file.json");
        File templateFile = null;
        try {
            templateFile = File.createTempFile("_tmp_" + System.nanoTime(), ".json");
            FileUtils.copyInputStreamToFile(resource.getInputStream(), templateFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String datafromFile = FileUtil.getDatafromFile(templateFile);
        tempTreeList = (List<LinkedHashMap<String, String>>) JSONUtils.parse(datafromFile);
        for (int i = 0; i < tempTreeList.size(); i++) {
            TabTree tree = new TabTree();
            tempTreeList.get(i).forEach((x, y) -> {
                if (x.equals("treeName")) {
                    tree.setTreeName(y);
                } else if (x.equals("fileType")) {
                    tree.setFileType(y);
                }
            });
            tree.setpId(tabTree.getId());
            tree.setTreeSort(i);
            tree.setIsLayer(0);
            treeList.add(tree);
        }
        tabTreeMapper.saveBatch(treeList);
    }

}
